(function (exports) {
    var MP3Recorder = function (config) {

        var recorder = this;
        var deviceList, context, processor, microphone;
        var mp3ReceiveSuccess, currentErrorCallback;
        config = config || {};
        config.sampleRate = config.sampleRate || 44100;
        config.bitRate = config.bitRate || 128;

        async function getMediaDeviceStream(deviceId) {
            try {
                // 获取所有媒体设备列表
                const devices = deviceList ? deviceList : await recorder.getDeviceList();
                // 查找指定deviceId的媒体输入设备
                const device = devices.find(d => d.kind === 'audioinput' || d.kind === 'videoinput' && d.deviceId === deviceId);
                if (device) {
                    // 如果找到了设备，则获取该设备的媒体流
                    const stream = await navigator.mediaDevices.getUserMedia({
                        audio: device.kind === 'audioinput' || device.kind === 'audiooutput',
                        // video: device.kind === 'videoinput'
                    });
                    return stream;
                } else {
                    if (config.funCancel) {
                        config.funCancel('当前浏览器不支持录音功能');
                    }
                }
            } catch (error) {
                console.error('获取媒体设备流失败:', error);
            }
        }

        function onError(error) {
            var msg;
            switch (error.code || error.name) {
                case 'PERMISSION_DENIED':
                case 'PermissionDeniedError':
                    msg = '用户拒绝访问麦客风';
                    break;
                case 'NOT_SUPPORTED_ERROR':
                case 'NotSupportedError':
                    msg = '浏览器不支持麦客风';
                    break;
                case 'MANDATORY_UNSATISFIED_ERROR':
                case 'MandatoryUnsatisfiedError':
                    msg = '找不到麦克风设备';
                    break;
                default:
                    msg = '无法打开麦克风，异常信息:' + (error.code || error.name);
                    break;
            }
            if (config.funCancel) {
                config.funCancel(msg);
            }
        }

        function onRecord(stream) {
            context = new AudioContext();
            microphone = context.createMediaStreamSource(stream);
            processor = context.createScriptProcessor(16384, 1, 1);//bufferSize大小，输入channel数，输出channel数
            config.sampleRate = context.sampleRate;

            var realTimeWorker = new Worker('js/worker-realtime.js');
            processor.onaudioprocess = function (event) {
                //边录音边转换
                var array = event.inputBuffer.getChannelData(0);
                realTimeWorker.postMessage({cmd: 'encode', buf: array});
            };
            realTimeWorker.onmessage = function (e) {
                switch (e.data.cmd) {
                    case 'init':
                        log('初始化成功');
                        if (config.funOk) {
                            config.funOk();
                        }
                        break;
                    case 'end':
                        log('MP3大小：', e.data.buf.length);
                        if (mp3ReceiveSuccess) {
                            mp3ReceiveSuccess(new Blob(e.data.buf, {type: 'audio/mp3'}));
                        }
                        break;
                    case 'error':
                        log('错误信息：' + e.data.error);
                        if (currentErrorCallback) {
                            currentErrorCallback(e.data.error);
                        }
                        break;
                    default:
                        log('未知信息：', e.data);
                }
            };
            recorder.getMp3Blob = function (onSuccess, onError) {
                currentErrorCallback = onError;
                mp3ReceiveSuccess = onSuccess;
                realTimeWorker.postMessage({cmd: 'finish'});
            };

            realTimeWorker.postMessage({
                cmd: 'init',
                config: {
                    sampleRate: config.sampleRate,
                    bitRate: config.bitRate
                }
            });
        }
        function log(str) {
            if (config.debug) {
                console.log(str);
            }
        }
        recorder.init = function (){
            if (config.deviceId) {
                console.log('deviceId is', config.deviceId);
                getMediaDeviceStream(config.deviceId).then(stream => {
                    onRecord(stream);
                }).catch(error => {
                    onError(error)
                });
            } else {
                console.log('deviceId is null');
                navigator.getUserMedia = navigator.getUserMedia ||
                    navigator.webkitGetUserMedia ||
                    navigator.mozGetUserMedia ||
                    navigator.msGetUserMedia;
                if (navigator.getUserMedia) {
                    navigator.getUserMedia({audio: true},
                        function (stream) {
                            onRecord(stream);
                        },
                        function (error) {
                            onError(error);
                        });
                } else {
                    if (config.funCancel) {
                        config.funCancel('当前浏览器不支持录音功能');
                    }
                }
            }
        }
        recorder.getConfig = function () {
            return config;
        }
        recorder.start = function (isSpeaker) {
            if (processor && microphone) {
                microphone.connect(processor);
                if(isSpeaker){
                    const destinationNode = context.createMediaStreamDestination();
                    microphone.connect(destinationNode);
                }
                processor.connect(context.destination);
                log('开始录音');
            }
        }
        recorder.stop = function () {
            if (processor && microphone) {
                microphone.disconnect();
                microphone = null;
                processor.disconnect();
                processor = null;
                context = null;
                log('录音结束');
            }
        }
        recorder.getDeviceList = async function () {
            deviceList = await navigator.mediaDevices.enumerateDevices();
            return deviceList;
        }
    }
    exports.MP3Recorder = MP3Recorder;
})(window);

